package com.ttg.web.service.Impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.handler.inter.IWriter;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ttg.common.entities.BasePage;
import com.ttg.common.entities.BaseResult;
import com.ttg.common.entities.UserTokenInfo;
import com.ttg.common.enums.*;
import com.ttg.common.exception.BaseException;
import com.ttg.common.utils.DateTimeUtil;
import com.ttg.common.utils.JsonUtils;
import com.ttg.common.utils.UserUtil;
import com.ttg.model.dto.*;
import com.ttg.model.dto.coupon.SendToCouponGetTagStatusDto;
import com.ttg.model.dto.coupon.TagUsedListDTO;
import com.ttg.model.mapper.TagInfoMapper;
import com.ttg.model.pojo.*;
import com.ttg.model.vo.*;
import com.ttg.model.vo.coupon.GradeTagListUsedVO;
import com.ttg.model.vo.coupon.SendToCouponGetTagStatusVo;
import com.ttg.web.dao.*;
import com.ttg.web.redis.RedissonUtils;
import com.ttg.web.service.EstimateTagInfoService;
import com.ttg.web.service.GradeToCouponService;
import com.ttg.web.service.ManageTagInfoService;
import com.ttg.web.service.TagInfoService;
import com.ttg.web.utils.NextUpdateTimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.redisson.api.RLock;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author ZQ
 * @version 1.0
 * @Description
 * @date 2021/1/15 17:08
 */
@Slf4j
@Service
public class TagInfoServiceImpl extends ServiceImpl<TagInfoMapper, TagInfo> implements TagInfoService {

    @Autowired
    private TagInfoDao tagInfoDao;
    @Autowired

    private TblTagInfoDao tblTagInfoDao;

    @Autowired
    private ConditionsInfoDao conditionsInfoDao;

    @Autowired
    private GradeToCouponService gradeToCouponService;

    @Autowired
    private VipBindTagDao vipBindTagDao;

    @Autowired
    private ConditionsNameDao conditionsNameDao;

    @Autowired
    private ManageTagInfoService manageTagInfoService;

    @Autowired
    private EstimateTagInfoService estimateTagInfoService;

    @Autowired
    private RedissonUtils redissonUtils;
    @Autowired
    private BankAgentDao bankAgentDao;
    @Autowired
    private CityDao cityDao;
    @Autowired
    private MerchantClassDao merchantClassDao;
    @Autowired
    private TagClassDao tagClassDao;

    @Value("${tap.TypePublic}")
    private Integer TagPublic;

    @Value("${tap.TypePrivate}")
    private Integer TagPrivate;

    @Autowired
    private AdminLogDao adminLogDao;
    @Autowired
    private AdminDao adminDao;

    @Override
    public BasePage<TagVo> tagPage(TagPageDTO reqDto) {
        if (Objects.isNull(reqDto)) {
            throw new BaseException(ErrorCodeEnums.PARAM_IS_NULL);
        }
        BasePage<TagVo> tagVoBasePage = tagInfoDao.tagPage(reqDto);
        // 如果列表为空，直接返回
        if (CollectionUtils.isEmpty(tagVoBasePage.getList())) {
            return tagVoBasePage;
        }
        if(1==1){
            getTagUsed( tagVoBasePage);
        }
        return tagVoBasePage;
    }

    public void getTagUsed( BasePage<TagVo> tagVoBasePage) {
        try{
            // 构建请求DTO
            TagUsedListDTO requestDto = new TagUsedListDTO();
            requestDto.setType("1");

            List<SendToCouponGetTagStatusDto> tagStatusDtoList = tagVoBasePage.getList().stream()
                    .map(tag -> {
                        SendToCouponGetTagStatusDto dto = new SendToCouponGetTagStatusDto();
                        dto.setType(1);
                        dto.setId(tag.getId());
                        return dto;
                    })
                    .collect(Collectors.toList());
            requestDto.setTagUsedList(tagStatusDtoList);

            // 获取标签使用状态
            GradeTagListUsedVO result = gradeToCouponService.getTagUsed(requestDto);

            // 构建标签状态映射表
            Map<Long, SendToCouponGetTagStatusVo> tagStatusMap = Optional.ofNullable(result.getGradeTagList()).orElse(Collections.emptyList()).stream().filter(vo -> vo.getId() != null).collect(Collectors.toMap(vo -> Long.valueOf(vo.getId()), // 将String类型的id转为Long
                    Function.identity(), (existing, replacement) -> existing));

            // 更新标签使用状态
            tagVoBasePage.getList().forEach(tag -> {
                if (tagStatusMap.containsKey(tag.getId())) {
                    tag.setTagUsed("1");
                }
            });
        } catch (Exception e){
            log.error("tagPage error"+e.getLocalizedMessage(),e);
        }

    }

    @Override
    @Transactional
    public BaseResult tagAdd(TagInfoDTO reqDto) {
        if (ObjectUtil.isEmpty(reqDto)) {
            throw new BaseException(ErrorCodeEnums.PARAM_IS_NULL);
        }
        reqDto.setTagUpdateTime(LocalDateTime.now().toLocalTime());
        paramValidation(reqDto);
        TblTagInfo tagInfo = new TblTagInfo();
        BeanUtil.copyProperties(reqDto, tagInfo);
        tagInfo.setAddTime(LocalDateTime.now());
        tagInfo.setUpdateTime(LocalDateTime.now());
        tagInfo.setAddId(UserUtil.getUserThrow().getAdmId());
        if (StringUtils.isBlank(tagInfo.getCreateType())) {
            tagInfo.setCreateType("customize");
        }
        //计算标签执行时间并保存
        LocalDateTime nextUpdateTime = NextUpdateTimeUtil.firstUpdateTime(tagInfo);
        tagInfo.setTagNextUpdateTime(nextUpdateTime);
        tblTagInfoDao.save(tagInfo);

        if (ObjectUtil.isNotEmpty(reqDto.getConditionsInfoDTOList())) {
            List<ConditionsInfo> conditionsInfoList = new ArrayList<>(reqDto.getConditionsInfoDTOList().size());
            reqDto.getConditionsInfoDTOList().forEach(conditionsInfoDTO -> {
                judgeData(conditionsInfoDTO);
                ConditionsInfo conditionsInfo = new ConditionsInfo();
                BeanUtil.copyProperties(conditionsInfoDTO, conditionsInfo);
                conditionsInfo.setTagId(tagInfo.getId());
                conditionsInfoList.add(conditionsInfo);
            });
            conditionsInfoDao.saveBatch(conditionsInfoList);
        }

        TagInfo tagInfo1 = tagInfoDao.getById(tagInfo.getId());
        if (ObjectUtil.isNotNull(tagInfo1)) {
            List<TagInfo> tagInfos = new ArrayList<>();
            tagInfos.add(tagInfo1);
            gradeToCouponService.sendToCouponTaggradeTagList(tagInfos);
        }
        return BaseResult.success(ResultStatusEnum.SUCCESS);
    }

    @Override
    public TagInfoVo tagInfo(TagPageDTO reqDto) {
        if (ObjectUtil.isEmpty(reqDto) || ObjectUtil.isEmpty(reqDto.getTagId())) {
            throw new BaseException(ErrorCodeEnums.PARAM_IS_NULL);
        }
        TblTagInfo tagInfo = tblTagInfoDao.getById(reqDto.getTagId());
        if (ObjectUtil.isEmpty(tagInfo)) {
            throw new BaseException(ErrorCodeEnums.TAG_NOT_EXISTS);
        }
        TagInfoVo tagInfoVo = new TagInfoVo();
        BeanUtil.copyProperties(tagInfo, tagInfoVo);
        tagInfoVo.setTagId(tagInfo.getId());

        TagClassVO parentClassInfo = tagClassDao.getParentClassInfo(tagInfo.getTagClassId());
        tagInfoVo.setTagClassId(Long.valueOf(parentClassInfo.getClassId()));
        tagInfoVo.setTagClassName(parentClassInfo.getClassName());
        tagInfoVo.setTagParentClassId(Long.valueOf(parentClassInfo.getClassParentId()));
        tagInfoVo.setTagParentClassName(parentClassInfo.getClassParentName());

        //查询条件list
        List<ConditionsInfoVO> conditionsInfoVOList = conditionsInfoDao.findConditionsByTagId(tagInfoVo.getTagId());
        tagInfoVo.setConditionsInfoVOList(conditionsInfoVOList);
        return tagInfoVo;
    }

    @Override
    @Transactional
    public BaseResult tagUpdate(TagInfoDTO reqDto) {
        if (ObjectUtil.isEmpty(reqDto) || ObjectUtil.isEmpty(reqDto.getTagId())) {
            throw new BaseException(ErrorCodeEnums.PARAM_IS_NULL);
        }
        TblTagInfo tagInfo = new TblTagInfo();
        reqDto.setTagUpdateTime(LocalDateTime.now().toLocalTime());
        BeanUtil.copyProperties(reqDto, tagInfo);
        tagInfo.setId(reqDto.getTagId());
        tagInfo.setUpdateTime(LocalDateTime.now());
        paramValidation(reqDto);
        //计算标签执行时间并保存
        LocalDateTime nextUpdateTime = NextUpdateTimeUtil.firstUpdateTime(tagInfo);
        tagInfo.setTagNextUpdateTime(nextUpdateTime);
        tblTagInfoDao.updateById(tagInfo);
        conditionsInfoDao.removeByTagId(reqDto.getTagId());
        if (ObjectUtil.isNotEmpty(reqDto.getConditionsInfoDTOList())) {
            List<ConditionsInfo> conditionsInfoList = new ArrayList<>(reqDto.getConditionsInfoDTOList().size());
            reqDto.getConditionsInfoDTOList().forEach(conditionsInfoDTO -> {
                judgeData(conditionsInfoDTO);
                ConditionsInfo conditionsInfo = new ConditionsInfo();
                BeanUtil.copyProperties(conditionsInfoDTO, conditionsInfo);
                conditionsInfo.setTagId(tagInfo.getId());
                conditionsInfoList.add(conditionsInfo);
            });
            conditionsInfoDao.saveBatch(conditionsInfoList);
        }

        TagInfo tagInfo1 = tagInfoDao.getById(tagInfo.getId());
        if (ObjectUtil.isNotNull(tagInfo1)) {
            List<TagInfo> tagInfos = new ArrayList<>();
            tagInfos.add(tagInfo1);
            gradeToCouponService.sendToCouponTaggradeTagList(tagInfos);
        }

        return BaseResult.success(ResultStatusEnum.SUCCESS);
    }

    private void paramValidation(TagInfoDTO reqDto) {
        if (StringUtils.isBlank(reqDto.getUpdateFrequency())) {
            throw new BaseException("更新频率类型不能为空");
        }
        if ((reqDto.getUpdateFrequency().equals(TagUpdateFrequencyEnum.WEEKLY.getValue()) || reqDto.getUpdateFrequency().equals(TagUpdateFrequencyEnum.MONTHLY.getValue()))) {
            if (StringUtils.isBlank(reqDto.getTagUpdateDates())) {
                throw new BaseException("更新频率不能为空");
            }
        }
        if (Objects.isNull(reqDto.getTagUpdateTime())) {
            throw new BaseException("更新时间不能为空");
        }
        if (CollectionUtils.isEmpty(reqDto.getConditionsInfoDTOList())) {
            throw new BaseException("条件列表不能为空");
        }

        List<ConditionsInfoDTO> conditionsInfoDTOList = reqDto.getConditionsInfoDTOList();
        for (ConditionsInfoDTO conditionsInfoDTO : conditionsInfoDTOList) {
            Long conditionsId = conditionsInfoDTO.getConditionsId();
            if (ObjectUtil.isNull(conditionsId)) {
                throw new BaseException(ErrorCodeEnums.PARAM_IS_NULL);

            } else {
                ConditionsName one = conditionsNameDao.getOne(new LambdaQueryWrapper<ConditionsName>().select(ConditionsName::getParamValidate).eq(ConditionsName::getId, conditionsId));
                if (ObjectUtil.isNull(one)) {
                    return;
                }
                String paramValidate = one.getParamValidate();
                if (ObjectUtil.isNotEmpty(paramValidate)) {
                    if (!Pattern.compile(paramValidate).matcher(conditionsInfoDTO.getData1()).matches()) {
                        throw new BaseException(ErrorCodeEnums.PARAM_VALIDATION_FAIL);
                    }
                    if (ExpressionTypeEnum.TYPE_BETWEEN.getValue() == conditionsInfoDTO.getConditionsExpressionId() || ExpressionTypeEnum.TYPE_NOT_BETWEEN.getValue() == conditionsInfoDTO.getConditionsExpressionId()) {
                        if (!Pattern.compile(paramValidate).matcher(conditionsInfoDTO.getData2()).matches()) {
                            throw new BaseException(ErrorCodeEnums.PARAM_VALIDATION_FAIL);
                        }
                    }
                }
            }
        }
    }

    private void judgeData(ConditionsInfoDTO conditionsInfoDTO) {
        int i = conditionsInfoDTO.getConditionsExpressionId().intValue();
        String data1 = conditionsInfoDTO.getData1();
        String data2 = conditionsInfoDTO.getData2();
        if (i == ExpressionTypeEnum.TYPE_EQUAL_TO.getValue()) {
            data2 = null;
        } else if (i == ExpressionTypeEnum.TYPE_NOTEQUAL_TO.getValue()) {
            data2 = null;
        } else if (i == ExpressionTypeEnum.TYPE_GREATER_THAN.getValue()) {
            data2 = null;
        } else if (i == ExpressionTypeEnum.TYPE_LESS_THAN.getValue()) {
            data2 = null;
        } else if (i == ExpressionTypeEnum.TYPE_GREATER_THAN_EQUAL_TO.getValue()) {
            data2 = null;
        } else if (i == ExpressionTypeEnum.TYPE_LESS_THAN_EQUAL_TO.getValue()) {
            data2 = null;
        } else if (i == ExpressionTypeEnum.TYPE_LIKE.getValue()) {
            data2 = null;
        }
        if (ObjectUtil.isNotNull(data1) && StringUtils.isBlank(data1)) {
            throw new BaseException(ErrorCodeEnums.PARAM_IS_NULL);
        }
        if (ObjectUtil.isNotNull(data2) && StringUtils.isBlank(data2)) {
            throw new BaseException(ErrorCodeEnums.PARAM_IS_NULL);
        }
    }


    @Override
    @Transactional
    public BaseResult tagUpdateStatus(TagPageDTO reqDto) {
        if (ObjectUtil.isEmpty(reqDto) || ObjectUtil.isEmpty(reqDto.getTagId())) {
            throw new BaseException(ErrorCodeEnums.PARAM_IS_NULL);
        }
        if (ObjectUtil.isEmpty(reqDto.getTagStatus())) {
            throw new BaseException(ErrorCodeEnums.PARAM_IS_NULL);
        }
        TagInfo byId = tagInfoDao.getById(reqDto.getTagId());
        if (ObjectUtil.isNull(byId)) {
            throw new BaseException(ErrorCodeEnums.PARAM_IS_NULL);
        }
        if (StatusEnum.DISABLE.getValue() == reqDto.getTagStatus() && (!gradeToCouponService.sendToCouponGetTagStatus(reqDto.getTagId()) || ObjectUtil.isNotNull(byId.getVipGradeId()))) {
            throw new BaseException(ErrorCodeEnums.TAG_IS_USED);
        }
        if (StatusEnum.ENABLE.getValue() == reqDto.getTagStatus()) {
            int count = tagInfoDao.count(new LambdaQueryWrapper<TagInfo>().eq(TagInfo::getTagType, byId.getTagType()).eq(TagInfo::getTagStatus, StatusEnum.ENABLE.getValue()));
            if ((TagTypeEnum.TYPE_PRIVATE.getValue() == byId.getTagType() && count >= TagPrivate) || (TagTypeEnum.TYPE_PUBLIC.getValue() == byId.getTagType() && count >= TagPublic)) {
                throw new BaseException(ErrorCodeEnums.TAG_LIMIT);
            }
        }

        tagInfoDao.update(new LambdaUpdateWrapper<TagInfo>().set(TagInfo::getTagStatus, reqDto.getTagStatus()).set(StatusEnum.DISABLE.getValue() == reqDto.getTagStatus(), TagInfo::getTagPeopleNumber, 0).eq(TagInfo::getId, reqDto.getTagId()));
        if (StatusEnum.DISABLE.getValue() == reqDto.getTagStatus()) {
            vipBindTagDao.removeByTagId(reqDto.getTagId());
        }
        byId = tagInfoDao.getById(reqDto.getTagId());
        if (ObjectUtil.isNotNull(byId)) {
            List<TagInfo> tagInfos = new ArrayList<>();
            tagInfos.add(byId);
            gradeToCouponService.sendToCouponTaggradeTagList(tagInfos);
        }
        return BaseResult.success(ResultStatusEnum.SUCCESS);
    }

    @Override
    public BasePage<TagVipVo> tagVipPage(TagVipPageDTO reqDto) {
        if (ObjectUtil.isEmpty(reqDto) || ObjectUtil.isEmpty(reqDto.getTagId())) {
            throw new BaseException(ErrorCodeEnums.PARAM_IS_NULL);
        }
        Set<String> agents = tagInfoDao.getAgents(reqDto);
        return tagInfoDao.tagVipPage(reqDto, agents, true);
    }


    @Override
    public void tagVipPageExport(TagVipPageDTO reqDto, HttpServletResponse response) {
        if (ObjectUtil.isEmpty(reqDto) || ObjectUtil.isEmpty(reqDto.getTagId())) {
            throw new BaseException(ErrorCodeEnums.PARAM_IS_NULL);
        }
        String fileName = "标签会员导出";
        String fileType = ".xlsx";
        int extCount = 0;
        reqDto.setPage(1);
        reqDto.setPageSize(1000);
        Set<String> agents = tagInfoDao.getAgents(reqDto);
        BasePage<TagVipVo> basePage = tagInfoDao.tagVipPage(reqDto, agents, true);
        List<TagVipVo> list = basePage.getList();
        List<TagVipVo> extList = new ArrayList<>();
        ExportParams params = new ExportParams(fileName + "导出时间：" + DateTimeUtil.formatYYYY_MM_DD_HH_MM_SS(LocalDateTime.now()) + "", "会员列表");
        params.setCreateHeadRows(true);
        IWriter<Workbook> workbookIWriter = ExcelExportUtil.exportBigExcel(params, TagVipVo.class);
//        Workbook workbook = ExcelExportUtil.exportExcel(params, TagVipVo.class,list);
        long total = basePage.getTotal();
        for (int i = 1; i <= 100; i++) {
            if (i != 1) {
                reqDto.setPage(i);
                basePage = tagInfoDao.tagVipPage(reqDto, agents, false);
            }
            list = basePage.getList();
            extCount += CollectionUtils.isEmpty(list) ? 0 : list.size();
            for (TagVipVo tempVo : list) {
                extList.add(tempVo);
            }
            list.clear();
            if (extCount >= total) {
                break;
            }
        }
        int size = extList.size();

        workbookIWriter.write(extList);
        Workbook workbook = workbookIWriter.get();
        if (workbook != null) {

            try (ServletOutputStream outputStream = response.getOutputStream()) {

                response.setCharacterEncoding("UTF-8");
                response.setHeader("content-Type", "application/vnd.ms-excel");
                response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(fileName + fileType, "UTF-8"));
                response.setHeader("Access-Control-Expose-Headers", "filename");
                response.setHeader("filename", java.net.URLEncoder.encode(fileName + fileType, "UTF-8"));
                workbook.write(outputStream);
                UserTokenInfo userThrow = UserUtil.getUserThrow();
                Admin admin = adminDao.getById(userThrow.getAdmId());
                TagInfo byId = tagInfoDao.getById(reqDto.getTagId());
                adminLogDao.addLog(userThrow.getAdmId(), 6L, "r", null, String.format("标签对私会员列表导出,标签编号:%s,标签名称:%s,导出数量:%s", byId.getId(), byId.getTagName(), size), userThrow.getIp(), admin.getAdmUserName(), admin.getAdmTrueName(), "标签管理");
            } catch (IOException e) {
                log.error("TagInfoServiceImpl.tagVipPageExport 导出异常", e);
                throw new BaseException(ErrorCodeEnums.EXPORT_IS_ERROR);
            }
        }
    }

    @Override
    public BasePage<TagMctVo> tagMctPage(TagMctPageDTO dto) {
        if (ObjectUtil.isEmpty(dto) || ObjectUtil.isEmpty(dto.getMctNo())) {
            throw new BaseException(ErrorCodeEnums.PARAM_IS_NULL);
        }
        return tagInfoDao.tagPageByMct(dto);
    }

    @Override
    public BasePage<MctTagPageVo> mctTagPage(MctTagPageDto dto) {
        if (ObjectUtil.isEmpty(dto) || ObjectUtil.isEmpty(dto.getTagId())) {
            throw new BaseException(ErrorCodeEnums.PARAM_IS_NULL);
        }
        BasePage<MctTagPageVo> mctTagPageVoBasePage = tagInfoDao.mctTagPage(dto);
        return mctTagPageVoBasePage;
    }

    @Override
    public void mctTagPageExport(MctTagPageDto reqDto, HttpServletResponse response) {
        if (ObjectUtil.isEmpty(reqDto) || ObjectUtil.isEmpty(reqDto.getTagId())) {
            throw new BaseException(ErrorCodeEnums.PARAM_IS_NULL);
        }
        String fileName = "标签商户导出";
        String fileType = ".xlsx";
        int extCount = 0;
        reqDto.setPage(1);
        reqDto.setPageSize(1000);
        BasePage<MctTagPageVo> basePage = tagInfoDao.mctTagPage(reqDto);
        List<MctTagPageVo> list = basePage.getList();
        List<MctTagPageVo> extList = new ArrayList<>();
        ExportParams params = new ExportParams(fileName + "导出时间：" + DateTimeUtil.formatYYYY_MM_DD_HH_MM_SS(LocalDateTime.now()) + "", "会员列表");
        params.setCreateHeadRows(true);
        IWriter<Workbook> workbookIWriter = ExcelExportUtil.exportBigExcel(params, MctTagPageVo.class);
//        Workbook workbook = ExcelExportUtil.exportExcel(params, MctTagPageVo.class,list);
        long total = basePage.getTotal();
        for (int i = 1; i <= 100; i++) {
            if (i != 1) {
                reqDto.setPage(i);
                basePage = tagInfoDao.mctTagPage(reqDto);
            }
            list = basePage.getList();
            extCount += CollectionUtils.isEmpty(list) ? 0 : list.size();
            for (MctTagPageVo tempVo : list) {
                extList.add(tempVo);
            }
            list.clear();
            if (extCount >= total) {
                break;
            }
        }
        int size = extList.size();
        workbookIWriter.write(extList);
        Workbook workbook = workbookIWriter.get();
        if (workbook != null) {

            try (ServletOutputStream outputStream = response.getOutputStream()) {
                response.setCharacterEncoding("UTF-8");
                response.setHeader("content-Type", "application/vnd.ms-excel");
                response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(fileName + fileType, "UTF-8"));
                response.setHeader("Access-Control-Expose-Headers", "filename");
                response.setHeader("filename", java.net.URLEncoder.encode(fileName + fileType, "UTF-8"));
                workbook.write(outputStream);
                UserTokenInfo userThrow = UserUtil.getUserThrow();
                Admin admin = adminDao.getById(userThrow.getAdmId());
                TagInfo byId = tagInfoDao.getById(reqDto.getTagId());
                adminLogDao.addLog(userThrow.getAdmId(), 6L, "r", null, String.format("标签收单商户列表导出,标签编号:%s,标签名称:%s,导出数量:%s", byId.getId(), byId.getTagName(), size), userThrow.getIp(), admin.getAdmUserName(), admin.getAdmTrueName(), "标签管理");
            } catch (IOException e) {
                log.error("TagInfoServiceImpl.mctTagPageExport 导出异常", e);
                throw new BaseException(ErrorCodeEnums.EXPORT_IS_ERROR);
            }
        }
    }

    @Override
    public BasePage<TagVo> tagPageByVip(TagVipPageDTO reqDto) {
        if (ObjectUtil.isEmpty(reqDto) || ObjectUtil.isEmpty(reqDto.getVipId())) {
            throw new BaseException(ErrorCodeEnums.PARAM_IS_NULL);
        }
        return tagInfoDao.tagPageByVip(reqDto);
    }

    @Override
    public BaseResult getVipTagList(GetVipTagListDto dto) {
        BasePage<Object> parse = dto.parse();
        BasePage<GetVipTagListVo> page = new BasePage<>(parse.getCurrent(), parse.getSize(), parse.getTotal(), parse.isSearchCount());
        BasePage<GetVipTagListVo> vipTagList = tagInfoDao.getVipTagList(page, dto);
        return BaseResult.success(vipTagList);
    }

    @Override
    public ResultStatusVo updateTagBind(TagBindDto tagBindDto) {
        if (Objects.isNull(tagBindDto) || Objects.isNull(tagBindDto.getTagId())) {
            throw new BaseException(ErrorCodeEnums.PARAM_IS_NULL);
        }
        TagInfo byId = tagInfoDao.getById(tagBindDto.getTagId());
        if (Objects.isNull(byId)) {
            throw new BaseException(ErrorCodeEnums.TAG_NOT_EXISTS);
        }

        List<ConditionsInfo> byTagId = conditionsInfoDao.findByTagId(byId.getId());
        if (CollectionUtils.isEmpty(byTagId)) {
            throw new BaseException(ErrorCodeEnums.RULES_IS_NULL);
        }
        RLock rLock = null;
        Integer tagHisId = manageTagInfoService.addTagHis(byId);
        try {
            rLock = redissonUtils.getRLock("TAG" + byId.getId());
            boolean redisFlag = rLock.tryLock(5, 60 * 5, TimeUnit.SECONDS);
            if (!redisFlag) {
                manageTagInfoService.updateTagHis(byId, tagHisId, VersionStatusEnum.FAIL.getCode(),null);
                throw new BaseException(ErrorCodeEnums.TAG_BIND_UPDATING.getErrcode(), ErrorCodeEnums.TAG_BIND_UPDATING.getMsg());
            }
            if (TagTypeEnum.TYPE_PRIVATE.getValue() == byId.getTagType()) {
                manageTagInfoService.asyncUpdateVipTag(tagBindDto.getTagId(), byTagId, null, tagHisId);
            } else if (TagTypeEnum.TYPE_PUBLIC.getValue() == byId.getTagType()) {
                manageTagInfoService.asyncUpdateMctTag(tagBindDto.getTagId(), byTagId, null, tagHisId);
            }

        } catch (BaseException baseException) {
            manageTagInfoService.updateTagHis(byId, tagHisId, VersionStatusEnum.FAIL.getCode(),null);
            throw baseException;
        } catch (Exception e) {
            manageTagInfoService.updateTagHis(byId, tagHisId, VersionStatusEnum.FAIL.getCode(),null);
            throw new BaseException("更新标签异常", e.getLocalizedMessage());
        } finally {
            if (Objects.nonNull(rLock) && rLock.isLocked()) {
                rLock.unlock();
            }
        }
        return new ResultStatusVo(ResultStatusEnum.SUCCESS.getCode());
    }

    @Override
    public BaseResult bankAgentList(BankAgentListDto reqDto) {

        List<BankAgentListVo> list = null;
        if (Objects.isNull(reqDto) || Objects.isNull(reqDto.getBankAgentNos()) || reqDto.getBankAgentNos().isEmpty()) {
            list = bankAgentDao.bankAgentList();
        } else {
            List<BankAgent> list1 = bankAgentDao.list(new LambdaQueryWrapper<BankAgent>().in(BankAgent::getBankAgentNo, reqDto.getBankAgentNos()));
            list = new ArrayList<>();
            for (BankAgent bankAgent : list1) {
                BankAgentListVo bankAgentListVo = new BankAgentListVo();
                bankAgentListVo.setBankAgentNo(bankAgent.getBankAgentNo());
                bankAgentListVo.setBankAgentName(bankAgent.getBankAgentName());
                list.add(bankAgentListVo);
            }
        }
        return BaseResult.success(list);
    }

    @Override
    public BaseResult cityList(CityListDto reqDto) {
        List<CityListVo> list = null;
        if (Objects.isNull(reqDto) || Objects.isNull(reqDto.getCityids()) || reqDto.getCityids().isEmpty()) {
            list = cityDao.cityList();
        } else {
            List<City> list1 = cityDao.list(new LambdaQueryWrapper<City>().in(City::getCityid, reqDto.getCityids()));
            list = new ArrayList<>();
            for (City city : list1) {
                CityListVo cityListVo = new CityListVo();
                cityListVo.setCityid(city.getCityid());
                switch (city.getCityLevel()) {
                    case "1":
                        cityListVo.setCityName(city.getProvince());
                        break;
                    case "2":
                        cityListVo.setCityName(city.getCity());
                        break;
                    case "3":
                        cityListVo.setCityName(city.getCounty());
                        break;
                    default:
                        break;
                }
                list.add(cityListVo);
            }
        }
        return BaseResult.success(list);
    }

    @Override
    public BaseResult merchantList(MerchantClassListDto reqDto) {
        List<MerchantListVo> list = null;
        if (Objects.isNull(reqDto) || Objects.isNull(reqDto.getClsIds()) || reqDto.getClsIds().isEmpty()) {
            list = merchantClassDao.merchantClassList();
        } else {
            List<MerchantClass> list1 = merchantClassDao.list(new LambdaQueryWrapper<MerchantClass>().in(MerchantClass::getClsId, reqDto.getClsIds()));
            list = new ArrayList<>();
            for (MerchantClass merchantClass : list1) {
                MerchantListVo merchantListVo = new MerchantListVo();
                merchantListVo.setClsId(merchantClass.getClsId());
                merchantListVo.setClsName(merchantClass.getClsName());
                list.add(merchantListVo);
            }
        }
        return BaseResult.success(list);
    }

    @Override
    public void export(TagPageDTO reqDto, HttpServletResponse response) {
        String fileName = "tagExport";
        String fileType = ".xlsx";
        int extCount = 0;
        reqDto.setPage(1);
        reqDto.setPageSize(1000);
        BasePage<TagVo> basePage = tagInfoDao.tagPage(reqDto);
        List<TagVo> list = basePage.getList();
        List<TagVo> extList = new ArrayList<>();
        ExportParams params = new ExportParams(fileName + "导出时间：" + DateTimeUtil.formatYYYY_MM_DD_HH_MM_SS(LocalDateTime.now()) + "", "标签列表");
        params.setCreateHeadRows(true);
        IWriter<Workbook> workbookIWriter = ExcelExportUtil.exportBigExcel(params, TagVo.class);
        long total = basePage.getTotal();
        for (int i = 1; i <= 100; i++) {
            if (i != 1) {
                reqDto.setPage(i);
                basePage = tagInfoDao.tagPage(reqDto);
            }
            list = basePage.getList();
            extCount += CollectionUtils.isEmpty(list) ? 0 : list.size();
            for (TagVo tempVo : list) {
                extList.add(tempVo);
            }
            list.clear();
            if (extCount >= total) {
                break;
            }
        }
        workbookIWriter.write(extList);
        Workbook workbook = workbookIWriter.get();
        if (workbook != null) {
            try (ServletOutputStream outputStream = response.getOutputStream()) {
                response.setCharacterEncoding("UTF-8");
                response.setHeader("content-Type", "application/vnd.ms-excel");
                response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(fileName + fileType, "UTF-8"));
                response.setHeader("Access-Control-Expose-Headers", "filename");
                response.setHeader("filename", java.net.URLEncoder.encode(fileName + fileType, "UTF-8"));
                workbook.write(outputStream);
            } catch (IOException e) {
                log.error("export tag 导出异常", e);
                throw new BaseException(ErrorCodeEnums.EXPORT_IS_ERROR);
            }
        }
    }

    @Override
    public BaseResult tagEstimate(TagInfoDTO reqDto) {
        log.info("tagEstimate param"+ JsonUtils.objectToJson(reqDto));
        if (TagTypeEnum.TYPE_PRIVATE.getValue() == reqDto.getTagType()) {
            return BaseResult.success(estimateTagInfoService.tagEstimateVip(reqDto));
        } else {
            return BaseResult.success(estimateTagInfoService.tagEstimateMct(reqDto));
        }
    }
}
